package view.overlay;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Rectangle2D;
import java.util.EnumMap;
import java.util.Map;

import stat.StatManager;
import stat.StatType;
import controller.SimpleMouseListener;

public class SkillPointAssignmentOverlay extends PassiveOverlay {
	
	// The stat manager to use
	private StatManager mStatsManager;
	
	// Is the main ui visible?
	private boolean mIsFullVisible;
	
	// Maps the stats to their bounding areas
	private EnumMap<StatType, Rectangle> mStatBounds;
	private EnumMap<StatType, Rectangle> mStatUpBounds;
	
	// Overall bounding rect for the main UI
	private Rectangle mBounds;
	
	// Toggle button to show/hide main UI
	private Button mToggleButton;
	
	// Padding for the main UI's bounds
	private int mPaddingTop;
	private int mPaddingLeft;
	private int mPaddingRight;
	private int mPaddingBottom;
	
	private Map<StatType, MouseListener> mListeners;
	
	private EnumMap<StatType, Integer> mStatValues;
	
	// Bounds for where we show the user how many points remain
	private Rectangle mStatPointsRemainingBounds;

	private StatType[] mUpgradeableStats;
	
	public SkillPointAssignmentOverlay(StatManager stats) {
		mStatsManager = stats;
		
		mUpgradeableStats = new StatType[0];
		
		// Default padding values
		mPaddingTop = 100;
		mPaddingLeft = 100;
		mPaddingRight = 100;
		mPaddingBottom = 100;
		
		mStatBounds = new EnumMap<StatType, Rectangle>(StatType.class);
		mStatUpBounds = new EnumMap<StatType, Rectangle>(StatType.class);
		
		mToggleButton = new Button("Skill Points");
		mToggleButton.setListener(new SimpleMouseListener() {

			@Override
			public void mouseClicked(MouseEvent e) {
				if (mIsFullVisible) {
					// hide it
					hideSkillPointAssigner();
				}
				else {
					showSkillPointAssigner();
				}
				
			}
		
		});
	}

	@Override
	protected void paint(Graphics g) {

		// Always want to draw the button at the top
		mToggleButton.draw(g);
		
		Rectangle2D textSize;
		
		if (mIsFullVisible) {
			
			// Draw background
			g.setColor(new Color(85, 81, 246, 100));
			g.fill3DRect(mBounds.x, mBounds.y, mBounds.width, mBounds.height, true);

			
			
			for (StatType s : mUpgradeableStats) {
				Rectangle rect = mStatBounds.get(s);
				
				if (rect == null) continue;

				g.setColor(Color.BLACK);
				g.fill3DRect(rect.x, rect.y, rect.width, rect.height, true);


				g.setColor(Color.GREEN);
				
				Rectangle upR = mStatUpBounds.get(s);
				if (upR != null) {
					g.fill3DRect(upR.x, upR.y, upR.width, upR.height, true);
				}
			
				int value = 0;
				if (mStatValues.containsKey(s)) {
					value = mStatValues.get(s).intValue();
				}
				
				String dispString = String.format("%s = %d", s.toString(), value);
				g.setColor(Color.WHITE);
				textSize = g.getFontMetrics().getStringBounds(dispString, g);
				g.drawString(dispString,
							(int)(rect.x + rect.width / 2 - textSize.getWidth() / 2),
							(int)(rect.y + rect.height / 2 + textSize.getHeight() / 2));
				
			}
			
			g.setColor(Color.black);
			
			// fill in points remaining
			g.fill3DRect(mStatPointsRemainingBounds.x,
					mStatPointsRemainingBounds.y,
					mStatPointsRemainingBounds.width,
					mStatPointsRemainingBounds.height, true);
			
			g.setColor(Color.WHITE);
			String dispString = String.format("Points: %d", mStatValues.get(StatType.STATPOINT));
			textSize = g.getFontMetrics().getStringBounds(dispString, g);
			g.drawString(dispString,
						(int)(mStatPointsRemainingBounds.x + mStatPointsRemainingBounds.width / 2 - textSize.getWidth() / 2),
						(int)(mStatPointsRemainingBounds.y + mStatPointsRemainingBounds.height / 2 + textSize.getHeight() / 2));
		}
	}
	
	public void setUpListeners(EnumMap<StatType, MouseListener> listeners) {
		mListeners = listeners;
	}
	
	public void setStatValues(EnumMap<StatType, Integer> values) {
		mStatValues = values;
		this.invalidate();
	
	}
	
	public void setUpgradeableStats(StatType[] types) {
		mUpgradeableStats = types;
	}
	
	public class SkillPointListener {
		private MouseListener upListener;
		private MouseListener downListener;
		
		public SkillPointListener(MouseListener up, MouseListener down) {
			upListener = up;
			downListener = down;
		}
		
		public MouseListener getUp() {
			return (upListener);
		}
		
		public MouseListener getDown() {
			return (downListener);
		}
		
	}
	
	private void calculateBounds() {
		
		int buttonWidth = 200;
		int buttonHeight = 20;
		mToggleButton.setBounds(this.getWidth() / 2 + buttonWidth + 10 - buttonWidth / 2,
								0,
								buttonWidth,
								buttonHeight);
		
		
		// Calculate overall bounds
		mBounds = new Rectangle(mPaddingLeft,
								mPaddingTop,
								getWidth() - mPaddingRight * 2,
								getHeight() - mPaddingBottom * 2);
		

		
		
		int boxHeight = 50;
		int boxWidth = 150;
		
		int boxVPadding = 10;
		int boxHPadding = 10;
		
		// x and y offsets
		int xOffset = boxHPadding;
		int yOffset = boxVPadding;
		
		// Go through the stats
		for (StatType s : mUpgradeableStats) {
			Rectangle rect = new Rectangle(mBounds.x + xOffset,
											mBounds.y + yOffset,
											boxWidth,
											boxHeight);
			
			mStatBounds.put(s, rect);
			yOffset += boxVPadding + boxHeight;
			
			if (mBounds.y + yOffset + boxHeight + boxVPadding > mBounds.y + mBounds.height){
				// move to next row
				yOffset = boxVPadding;
				xOffset += boxWidth + boxHPadding;
			}
			
			buttonWidth = 25;
			buttonHeight = rect.height;
			
			Rectangle upR = new Rectangle(rect.x + rect.width - buttonWidth,
											rect.y,
											buttonWidth,
											buttonHeight);
			mStatUpBounds.put(s,  upR);
		}
		
		boxWidth = 100;
		boxHeight = 40;
		
		 mStatPointsRemainingBounds = new Rectangle(mBounds.x + mBounds.width - boxWidth - boxHPadding,
				 									mBounds.y + boxVPadding,
				 									boxWidth - boxHPadding,
				 									boxHeight);
	}
	
	@Override
	public void onMouseClicked(MouseEvent e) {
		Point p = e.getPoint();
		if (mToggleButton.contains(e.getPoint())) {
			mToggleButton.activate(e);
		}
		
		// check for the
		for (StatType s : mUpgradeableStats) {
			// Get the bounds
			Rectangle up = mStatUpBounds.get(s);
			if (up != null) {
				if (up.contains(p)) {
					// call listener
					MouseListener listener = mListeners.get(s);
					
					if (listener != null) {
						listener.mouseClicked(e);
					}
				}
			}
			

		}
	}

	@Override
	public Dimension getPreferredSize() {
		return new Dimension(0, 0);
	}
	
	
	public void showSkillPointAssigner() {
		mIsFullVisible = true;
		this.invalidate();
	}
	
	public void hideSkillPointAssigner() {
		mIsFullVisible = false;
		this.invalidate();
	}
	
	@Override
	public void resize(int width, int height) {
		super.resize(width, height);
		
		calculateBounds();
		
		this.invalidate();
	}
	
	/**
	 * Toggles the visibility of the inventory
	 */
	public void toggleSkillPointAssigner() {
		if (mIsFullVisible) {
			hideSkillPointAssigner();
		}
		else {
			showSkillPointAssigner();
		}
	}
	
}
